#include "Test.Font.h"

#undef  APP_NAME
#define APP_NAME	TestSensorGPS
#undef  APP_BASE
#define APP_BASE	TestFont


class APP_NAME : public APP_BASE
{
	typedef SHARED_POINTER_TYPE( APP_NAME )		TestSensorGPSPtr;

private:
	array< dvec2 >		points;
	SysEvent::Location	loc;
	GeoLocation			prevLoc;


public:
	APP_NAME (IPlatform *platform, EDevice::type deviceType) :
		APP_BASE( platform, deviceType )
	{
		ZeroMem( loc );

		ESS()->GetEventSystem()->AttachEventListener(
			DelegateBuilder::Create( TestSensorGPSPtr(this), &APP_NAME::_OnLocation ),			ESystemEvent::LOCATION );

		ESS()->GetEventSystem()->AttachEventListener(
			DelegateBuilder::Create( TestSensorGPSPtr(this), &APP_NAME::_OnLocationStatus ),	ESystemEvent::LOCATION_STATUS );
	}


	~APP_NAME ()
	{
		ESS()->GetEventSystem()->DetachEventListener(
			DelegateBuilder::Create( TestSensorGPSPtr(this), &APP_NAME::_OnLocation ),			ESystemEvent::LOCATION );

		ESS()->GetEventSystem()->DetachEventListener(
			DelegateBuilder::Create( TestSensorGPSPtr(this), &APP_NAME::_OnLocationStatus ),	ESystemEvent::LOCATION_STATUS );
	}


	void Update (float dt) override
	{
		TestApp::Update( dt );
		
		ESS()->GetGraphicsEngine()->GetViewport()->Apply();
		ESS()->GetGLStateManager()->ClearColor( color4f( 0.0f ) );
		
#		define F( x )	string().FormatF( x, StringFormatF().Fmt(0,2) )

		dvec2	dp;

		if ( not points.Empty() )
			dp = points.Back();

		string	str;

		str << "lat:      "   << F( loc.lat )
			<< "\nlon:      " << F( loc.lon )
			<< "\nspeed:    " << F( loc.speed )
			<< "\nalt:      " << F( loc.altitude )
			<< "\naccuracy: " << F( loc.accuracy )
			<< "\ndelta x:  " << F( dp.x )
			<< "\ndelta y:  " << F( dp.y );
		
#		undef F

		fontBatch.Draw( vec2(-0.9f, 0.5f), str );

		batch.Flush();
		batch.Clear();
		
		ESS()->GetGraphicsEngine()->SwapBuffers();
	}
	

	void OnEnter () override
	{
		APP_BASE::OnEnter();
		
		material.SetColorState( RenderState::ColorState() );
		
		_GetLogger()->Open( "log/log", false );

		GetPlatform()->EnableSensor( ESensor::LOCATION );
	}


	void AddPoint (const dvec2 &p)
	{
		GeoLocation	gloc;

		gloc.FromDegrees( p.x, p.y );

		dvec2	v = prevLoc.Vector( gloc );

		if ( IsZero( v ) )
			return;

		prevLoc = gloc;

		//points.PushBack( v );

		// TODO
	}

	
	void _OnLocation (const SysEvent &ev)
	{
		AddPoint( dvec2( ev.location.lon, ev.location.lat ) );

		loc = ev.location;

		LOG( (string("GPS - lat:") << ev.location.lat << ", lon:" << ev.location.lon
					<< ", speed:" << ev.location.speed << ", alt:" << ev.location.altitude
					<< ", acc:" << ev.location.accuracy ).cstr(), ELog::INFO );
	}

	
	void _OnLocationStatus (const SysEvent &ev)
	{
		switch ( ev.locStatus.status )
		{
			case SysEvent::LocationStatus::DISABLED :
				LOG( "GPS disabled", ELog::INFO );
				break;
				
			case SysEvent::LocationStatus::ENABLED :
				LOG( "GPS enabled", ELog::INFO );
				break;
		}
	}
};